// XML.cpp:
//
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "XML.h"

// Convert Windows code page 1252 to Unicode UTF-8
// Taken from:
// http://discuss.joelonsoftware.com/default.asp?joel.3.325282.13

// Windows code page 1252 entries 0x80 to 0x9f
static const unsigned s_anCP1252_128to159[] =
{
   8364, 129, 8218, 402, 8222, 8230, 8224, 8225,
   710, 8240, 352, 8249, 338, 141, 381, 143,
   144, 8216, 8217, 8220, 8221, 8226, 8211, 8212,
   732, 8482, 353, 8250, 339, 157, 382, 376
};

std::string CP1252toUTF8( const char* szStr )
{
   const unsigned char* pSource = reinterpret_cast<const unsigned char*>(szStr);
   std::string strResult;
   int nLen = strlen( szStr );
   strResult.reserve( nLen + nLen/10 );
   unsigned cSource = *(pSource);
   while ( cSource )
   {
      if ( cSource >= 128 )
      {
         // convert CP1252 to Unicode point
         if ( cSource <= 159 )
            cSource = s_anCP1252_128to159[ cSource - 128 ];
         // encode Unicode point as UTF-8
         if ( cSource < 0x800 )
         {
            strResult += (char)(((cSource&0x7c0)>>6) | 0xc0);
            strResult += (char)((cSource&0x3f) | 0x80);
         }
         else
         {
            strResult += (char)(((cSource&0xf000)>>12) | 0xe0);
            strResult += (char)(((cSource&0xfc0)>>6) | 0x80);
            strResult += (char)((cSource&0x3f) | 0x80);
         }
      }
      else
         strResult += cSource;
      cSource = *(++pSource);
   }
   return strResult;
}

std::string sanitizeForXML (const std::string& input)
{
  return CP1252toUTF8 (input.c_str());
}

// ---------------------------------------------------------------

XMLNode::XMLNode (XMLNode* pParent, std::string name, AttribMap attrib)
  : m_Node (name), m_pParent (pParent)
{
  SetAttributes (attrib);
}

void XMLNode::SetAttributes (AttribMap attrib)
{
  AttribMap::iterator itor = attrib.begin ();
  for (; itor != attrib.end (); ++itor)
  {
    m_Node.SetAttribute(itor->first, sanitizeForXML (itor->second));
  }
}

void XMLNode::AddChild (XMLNode* pChild)
{
  m_Node.InsertEndChild(pChild->m_Node);
}

void XMLNode::AddText (XMLText* pContent)
{
  m_Node.InsertEndChild(pContent->m_Text);
}

void XMLNode::SetText (std::string text)
{
  TiXmlText xmlText (sanitizeForXML (text));
  m_Node.InsertEndChild(xmlText);
}

XMLNode::~XMLNode ()
{
  if (m_pParent) 
    m_pParent->AddChild (this);
}

// ---------------------------------------------------------------
XMLText::~XMLText ()
{
  if (m_pParent)
    m_pParent->AddText(this);
}


void XMLText::SetValue (std::string value)
{
  m_Text.SetValue (sanitizeForXML (value));
}


